#include "type.h"
#include "pic.h"
#include "keyboard.h"
#include "keymap.h"
#include "message.h"
/*----------------------外部引用--------------------------*/
//IO模块
void out_byte(u8,u16);
u8 in_byte(u16);
//显示模块
void disp_int(u32);
void dispStr(char*);
void dispChar(char);
//消息模块
void recv2(Message*);  
void send2(Message*);  
/*---------------------------------------------------------*/

/*-----------------------模块内部数据---------------------*/
#define SIZE	512
static 	boolean	i=True;
static  u32 buf[SIZE];
static 	unsigned char head,tail;
static  unsigned char shift;
static  unsigned char caps;
static	Message msg;
/*--------------------------------------------------------*/

/*-----------------------模块内部函数---------------------*/
static void put_code(u32 code);
static u32 get_code(void);
/*---------------------------------------------------------*/
/**
*初始化键盘程序
**/
void init_keyboard(void){
	head=0;
	tail=SIZE-1;
	shift=caps=0;
}

/**
*键盘服务器程序
**/
void keyboard_server(void){
	int head; //队列尾
	int tail; //队列尾
	int size; //缓冲区大小
	while(1){
		recv2(&msg); //接受消息如果信箱为空 则阻塞该进程
		head=msg.m.m2.head; //取得消息队列的头
		tail=msg.m.m2.tail; //取得消息队列的尾	
		size=msg.m.m2.size;//取得消息中键盘的缓冲区的大小

		//判断队列是否已经满了
		if((tail+1)%size==head){
			//如果满了 忽略
		}else{
			tail=(tail+1)%size;
			u32 code;
			if((code=get_code())){ //如果有键盘按下
			msg.m.m2.buf[tail]=code;
			msg.m.m2.tail=tail; //更新队列尾 
			}
		}
		/**
		*重新发送消息
		**/
		dispStr("the src=>");
		disp_int(msg.p_src);
		dispStr("\n");
		msg.p_dest=0;
		send2(&msg);	
	}
}


/**
*键盘队列 写数据
**/
static void put_code(u32 code){
	buf[tail]=code;
	tail=(tail+1)%SIZE;
}
/**
*键盘队列 读数据
**/
static u32  get_code(void){
	u32 code;
	head=(head+1)%SIZE;
	code=buf[head];
	buf[head]=0; //设置为空
	return code;
}
/**
*键盘中断处理程序
**/
void key_handler(void){
		//从硬件读取键盘码
		u32 code=(u32)in_byte(0x60);
		//如果键盘码为左Shift码或右Shift码被按下
		if(code==0x2A||code==0x36){
			shift=1;
			return;
		}
		//如果键盘码为左Shift码或右Shift码被释放
		if(code==0xAA||code==0xB6){
			shift=0;
			return;
		}
		if(i){ //如果键盘被按下
			//如果CapsLock键被按下
			if(code==0x3A)
				caps=caps^0x1;
			else{
	//		dispChar('c');
			dispStr(&keymap[3*code+(shift^caps)]);
			/**
			*将得到的键盘码放入队列中
			**/
			put_code(keymap[3*code+(shift^caps)]);
			}
			i=False;
		}else
			i=True;
		out_byte(0x20,EOI);	//对硬件写入EOI
}
